﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XMLSpreadGear.Headers;
using System.Xml;

namespace XMLSpreadGear.Core
{
    public abstract class Processor
    {
        private Styles m_styles;
        private Queue<Job> jobque;
        private XmlDocument m_xdoc;
        private ProcessHandler _handler;

        public Processor(Styles styles)
        {
            this.m_styles = styles;
            jobque = new Queue<Job>();
            m_xdoc = new XmlDocument();
        }

        /// <summary>
        /// This event will be triggered by the Process method.
        /// This event needs to handle at client side.  it will returns
        /// the generated xmldocument.
        /// </summary>
        public event ProcessHandler ProcessComplete
        {
            add
            {
                _handler = (ProcessHandler)Delegate.Combine(_handler, value);
            }
            remove
            {
                _handler = (ProcessHandler)Delegate.Remove(_handler, value);
            }
        }

        /// <summary>
        /// Adds a new job in the queue for the xml tranformation.
        /// </summary>
        /// <param name="jobItm">new instance of Job to be added</param>
        public void Add(Job jobItm)
        {
            jobque.Enqueue(jobItm);
        }
        internal Job GetNextJob()
        {
            return jobque.Dequeue();
        }

        protected Styles Styles
        {
            get { return this.m_styles; }
        }
        protected XmlDocument XmlDoc
        {
            get { return this.m_xdoc; }
        }

        public virtual void Process()
        {
            CreateProcessingInstructions();

            CreateHeaderTemplate();

            CreatePageTemplate();
        }

        protected void OnProcessCompletion()
        {
            if (_handler != null)
            {
                _handler(this, new ProcessHandlerArgs(this.XmlDoc));
            }
        }

        protected virtual void CreateProcessingInstructions()
        {
            XmlProcessingInstruction instruction;
            instruction = this.XmlDoc.CreateProcessingInstruction("xml", "version='1.0'");
            this.XmlDoc.AppendChild(instruction);
        }

        protected abstract void CreateHeaderTemplate();
        protected abstract void ProcessJob(Job jobToProcess);

        protected virtual void CreatePageTemplate()
        {
            while (this.jobque.Count > 0)
            {
                Job job = this.jobque.Dequeue();
                ProcessJob(job);
            }
        }
    }
}
